package dao;

import interfaces.IdAutoIncrement;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import model.Hospedagem;
import model.Hospede;
import model.Hotel;

@SuppressWarnings("serial")
public class Container implements Serializable {
	
	/**
	 * Container �nico que representa o arquivo na memoria.
	 */
	private static Container container = null;
	/**
	 * Nome do arquivo onde os objetos ser�o salvos.
	 */
	private final static String nomeBanco = "banco.hilton";
	
	/* Listas */
	private List<Hotel> hoteis;
	private List<Hospede> hospedes;
	private List<Hospedagem> hospedagens;
//	private List<Hospedagem> reservas;
	
	private Container() {
		hoteis = new ArrayList<Hotel>();
		hospedes = new ArrayList<Hospede>();
		hospedagens = new ArrayList<Hospedagem>();
//		reservas = new ArrayList<Hospedagem>();
	}
	
	/**
	 * Utiliza o padr�o Singleton para fazer com que o objeto seja �nico em toda a aplica��o.
	 * Caso o container ainda n�o exista, o metodo cria um, carrega os dados do arquivo e retorna a referencia do container.
	 * @return O container unico do sistema
	 */
	public static Container getInstance() {
		if (container == null) {
			container = new Container();
			openFile();
		}

		return container;

	}
	
	/**
	 * Carrega o container com os dados encontrados no arquivo.
	 */
	public synchronized static void openFile() {
		try {
			File banco = new File(nomeBanco);
			if (banco.exists()) {
				ObjectInputStream objReader = new ObjectInputStream(new FileInputStream(banco));
				container = (Container) objReader.readObject();
				objReader.close();
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}

	}
	
	/**
	 * Salva os dados do container em arquivo
	 */
	public synchronized static void saveFile() {
		try {
			File banco = new File(nomeBanco);
			ObjectOutputStream objWriter = new ObjectOutputStream(new FileOutputStream(banco));
			objWriter.writeObject(container);
			objWriter.flush();
			objWriter.close();
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * Retorna todos os objetos da classe informada.
	 * @param classe Nome da classe
	 * @return Uma List se a classe for persistivel. Null caso contrario.
	 */
	@SuppressWarnings("rawtypes")
	public List getList(String classe) {
		if (classe.equals("model.Hotel"))
			return hoteis;
		if (classe.equals("model.Hospede"))
			return hospedes;
		if (classe.equals("model.Hospedagem"))
			return hospedagens;
		return null;
	}
	
	/**
	 * Gera a Id dos objetos automaticamente de acordo com sua classe.
	 * @param classe Nome da classe
	 * @return 0 se for o primeiro objeto persistido da classe. O proximo Id caso contrario.
	 */
	@SuppressWarnings("rawtypes")
	public int gerarId(String classe) {
		List lista = getList(classe);
		if(lista.size() == 0)
			return 0;
		
		Object obj = lista.get(lista.size() - 1);
		return ((IdAutoIncrement) obj).getId() + 1;
		
	}
	
	
	/*
	 * Get/Set
	 */
	public List<Hotel> getHoteis() {
		return hoteis;
	}

	public void setHoteis(List<Hotel> hoteis) {
		this.hoteis = hoteis;
	}

	public List<Hospede> getHospedes() {
		return hospedes;
	}

	public void setHospedes(List<Hospede> hospedes) {
		this.hospedes = hospedes;
	}
	
	public List<Hospedagem> getHospedagens() {
		return hospedagens;
	}
	
	public void setHospedagens(List<Hospedagem> hospedagens) {
		this.hospedagens = hospedagens;
	}
	
//	public List<Hospedagem> getReservas() {
//		return reservas;
//	}
//	
//	public void setReservas(List<Hospedagem> reservas) {
//		this.reservas = reservas;
//	}

}
